// Copyright lowRISC contributors (OpenTitan project).
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/dif/dif_spi_device.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/spi_device_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_console.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"

#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"

OTTF_DEFINE_TEST_CONFIG(.console.type = kOttfConsoleSpiDevice,
                        .console.base_addr = TOP_EARLGREY_SPI_DEVICE_BASE_ADDR,
                        .console.test_may_clobber = false, );

static const char kTestStr[] = "This is a SPI device OTTF console test.";
static const char kTest64bDataStr[] =
    "940A859A712AC746E1290824993C8C3F1F42E4C282625BD97505B318B7018EA9";
static const char kTest256bDataStr[] =
    "E91258D174A16ADB6E516D494FDBAC5D09AE7E674F7CA413ACC7F429389275A52437E3EAA4"
    "3A7C923659D9F7568CA777FE84EBF7178DBEC876A02B93C283DDCCAC9FFA34A8A069110E57"
    "81E2755946689DBE4E8EB168F5974BA140646DDD391BAB6EF3D18F174356FC74789363080E"
    "2DC7616744DA5AC3735E33895E061745A9";
static const char kTest1KbDataStr[] =
    "2A2AFF29DE2892AEC5938694E773D801C1F354E9A94CCDF06CBCDED749EE1AA006CB04E3F3"
    "FFC441DBC0525C7968B5960C9740A1253E128886C9B4FE5AAD064F9D602B975CD48380B8D1"
    "C1873BC83D7141993F438609709240B3B36C248CA2EB342E05DDAE72F60F8ED2C938C266B5"
    "6AC1DC38F5EEFDD15D2334924FEC8FA87013C4715E9581C51B71159CA998A9F8E689E1B8D8"
    "2189914B6F0CA8C44AD3C5B6E306B4357E138DF6D76D802D62D9DF69F3351C97160C9A02AC"
    "00D114CD6E5A04A8EB41A244793D3A43E44FDF214E98BB64BC6F3E163E5CEA7E600577DA91"
    "40B6C03F827AD525F68781A1928995D1F23EAFC0CC8C72BD9F15A65E6D9294C54E2347BEF5"
    "3F0C727F3094D79E62B5C786FB8E380F6A3ABDB5165868ABA16E259E99234935F33CE1DFC3"
    "82B25A5B85CD946A99681D2FA95A4C7C9A33003ACD3F1B425AED858279FFECA1567C290E5B"
    "6474D5DCA7AC080F61D30D0DFC79D660AD51A499479F2CF16381AA012A892D97CD7AE56A7A"
    "3D4D5590E93B9496A718B31105D97B6B10F1742059693A99B88F0D59DAC2BDF12439D9E0F6"
    "3B2AFD642D4DBC17E2740D1E2C4195AC232FAAE7889695A24939C6D4D9A783F62E3A865A1C"
    "15233E06BD550B59D63603A880FE1A8BADD485F8A46E458A21671CD129C2B7565AC66EAF44"
    "DFBAED16FB4651C7C8AB4ADDAEB38346DA34E31B843FA087DC943A2DF353F9";
static const char kTest4KbDataStr[] =
    "7DFE2CE348C0FEDAA45BCBA3567B69B4F33E8E6E980A1242FDBE3150BACC15783D9F39F9D3"
    "6C98837A9EF05B1F24DB6460B73A90BD120D677AA12E1B5C1056D5B4A345D20CAA77B14D26"
    "FAB6BEE7C3136BFC3501AF94114E3E8AF2C94495BE2F1951B379B101E0C7CF3E29BCE4311D"
    "F85414B555C7C06654D5879876C004D258F422DF382FB064C843CBE9C90D35510E96E6E77B"
    "30FCF260559D5D535A73525BCACB3C295291F25F0C5C608D0CA0E5630AE8F26420AF3A4DB4"
    "7CDCA659A4CD09928DDAB796AB217FC5EEFE058D89CF3CC1CC19CC5CA31A5573966EABB05C"
    "2A3157F875A4717D7FE863F5E8EE338EADC2640CBD0671CB029764C9B8BE713E0BF93039F4"
    "3FD7BBB8DEFECEAD60126359E7A59E49A456C9C97C3E175C158AFC0DD806A4383B750A5B73"
    "B4DD1A60D7666F7B6BE0F85652CB726396F02382151CB05FE181910E765534CA17D8A5EF50"
    "7B883DD7430FAEF0029E664D7692FD2729F8CB8A002D7CB7EBBE2BD02FDB727959C9565150"
    "24CDBE1ADA3CA9466250F2F57ACA599692763B530BDB7DD1448FA5C5E42EA3E7D47CDF30D9"
    "AB3B90AB04C3057A0D87B3C695585A22FF2CEC1AD62C15CC6078B35F838A14EE9AA41191B1"
    "A149BE9F0FBBCD803AE2369E47B4BC64B5980B3B29C8E7DAC5DA4DC31F1384591B6EC0598F"
    "241E0FF539A1C63C3FD3F7BF5092C87C6452D0DF93B2CB5C60B6ED1582D42C46402340F59C"
    "D338946220CA6C5AD9577C216501DBCA53794FDF9B80A45A063D2D9E78CD6C795673AFC149"
    "685ACA6938062EFAF6435D8425141405FDBCA27EA6A8D23ED90E2475C4987B25DCE41FCDF3"
    "37672B9D7E9429B0827AE7223CDEABCDEFEC8C8568F4DF0C582D3A3B92C19485DED796F6B3"
    "E54424ED3D46F12E7620A8A9FBDE8432292B0F7F23F40407A4C38E06991B6146008AC6DA07"
    "194243BDF3F1966F1D126ED3570616BC03386CAC32FF4FC653C3F29C243F181E87AFA70FC1"
    "5499E95D678BBF15192A06793D952EAE54E3E1A414992237BD6F5594288A57BF3B1C255D1C"
    "6B3A26173BFBDBB622487ABE7A69EA308A7891E9FE6EA8C91C6189FB4E1C33798C4BD2B3B0"
    "6B2B254BDC59B8BDBDB127C28630634374E9C0EBA8F2706B9527120A412F2485B0AAEDA3A5"
    "2BB8013854E6FF2E36BA3F5C8951036B5198DAA549C9AC72897661C31BC887658C98698BB9"
    "6473FA227C65E010D3EF9E146B5AF5C0DEC6A07AB99F6F29304718E3893FF0DC33B68530A1"
    "3BACDC7782EB462CD8E6542843FB043FD95A36609A5FF1915AB309107BC9B26321A4D12A2F"
    "023EEF0ADFE901B7B1E38C9F288830407CDC4AD4BAAB2F0B4598E7CA47EA1EFA7270340A24"
    "064ED47697AEC4C15AAE7EF0862819375E7937AD366FAF069367A044B2AD73ED9ED3ED6213"
    "7F6158ADC543FB223D7F3C7C0668D4E22C09641EA9AFF2CA99A1A9515098C68287C9C55B52"
    "5C41A04BFE96E835E0B059712CBE57CE6F48DCF56F8FB8497E694CA0654DD3AB7BCB29FDA0"
    "1952A5CA81964D902744A2652A0D5F878EFC84EA233B6FFEEB6F65DBA1FC0CABFC4F317FA8"
    "C6A2AD89B1FA47E04C9423F3AC4DA988D56EC5FD6ACDC5FDB030DA6194DFB31A34567ADF1A"
    "B570A2C96AF0B8CC1BCE3120C6629D3C722515CB503E2D5A57DB546169D6CB24A937AEAF12"
    "DFA2CA55C8D2D952BC3C306901A74A1998465739FABF55F5465481177835D646BD957669E8"
    "6B828A1CC8432F54F67063ED9EF75C54D77F73D78009C10FA230A71A601BA7964B9106A765"
    "CFFF95108B392672874E85D9CD16383345468095333B996EDEC80F9089DF422112C9596A37"
    "BC426B7B134DB5D0116D71E07F552257D8F9706D504D2891E811F11A851092C26059525539"
    "08682BEDB6E989C2C6BCD08BA56ACABA4E64836F55D399976791067C7DFF083CCA6EA0AB29"
    "D8B4220D8EA09CD62F68A25F66B218C064E9E6125D8D1F8D02445BC3D70CD6F97322384361"
    "682E0B68ACBBE6522E9DFC5390C5244678C65A1D7D8512D0B964AA04748C586EAB35AEDDAE"
    "BC69350DDB6695353819D927B3C699305C4B93A42D1E848692FB240B4BD67CB53FDA99938B"
    "6B570F28DF6F32FABF95D5765BA833ECB424AE82EAF2C7C27E7294169DDD5B9F6753B80798"
    "6A0B68C93A20ACDB8D6F06C00E4B4292717BF3F9997BF653C347FDFBC5FCA166AAD2535DB1"
    "94006A3BC7B7B6BA16848326CE291E9DCA6BACB152956049619759B694FF709D215A209F28"
    "91B085D91868C614B57E5469A918424B5124AD9FD5085DC7EA438CF0BB805DEE55A6946E49"
    "0322C79816A3524F13B8175320E2CDFCE7BD2FBE611C85344784575EB6B3C07C4E72DD4248"
    "A421D4012BEB80BE8D86A29A5BFBF0A81B8CE9FB4B5C17577406F7A30B9A68A67B2C044D5D"
    "0BF5D819CD3198768022F784F1ED51E52DA691371CB545D0CAF25F8FCDF48CE855CC232E1D"
    "5F931DEB92F787E11F1C6FC25530B39824499E7A0774982A105FC952999DA0B3E79E3815DA"
    "CC6C7993DF8562F939F92DA1E3A2D538ADE55A534C11FA5B41983E536B3ECA2439160F49EE"
    "2638220E062BAA4C47708C7B9337DB5CF79EB2F9244B7F4D1A10168F7DBC6120AEDC45A53D"
    "A74C03244D7F30D211CD3153BE672A105AA8F301D2AA6179525E4C743DCC4C4764FB369063"
    "76F30800A18A07BC8FD17B800455B0B79D488C1B067958DB0B98E8A1203A3498382016A93D"
    "65C5D6B6F064931E0F96AF346EF447BC0BB1E33B160A145491C321934DB544813EA041EB66"
    "B30518D571FDD6D38E0477F6CB83C7729A45494F5D7805CCC1432C816B7D8CB089CEA56216"
    "9489E4F80E70FA685F39E1CD0AD7AD703C2E9601D442004F3D4CE043F0E84007FB7438FE82"
    "DF4D9304C90B48BB25762DD29D";

static uint8_t input_buf[5120];

bool test_main(void) {
  LOG_INFO("Sending empty string to Host...");
  LOG_INFO("");
  LOG_INFO("Sending test string to Host...");
  LOG_INFO("%s", kTestStr);
  LOG_INFO("SYNC: Waiting for console data");
  size_t received_data_len = ottf_console_spi_device_read(
      ottf_console_get(), sizeof(input_buf), input_buf);
  CHECK(received_data_len == sizeof(kTestStr));
  CHECK_ARRAYS_EQ(input_buf, kTestStr, ARRAYSIZE(kTestStr));

  LOG_INFO("Sending 64B data to Host...");
  LOG_INFO("%s", kTest64bDataStr);
  LOG_INFO("SYNC: Waiting for console data");
  received_data_len = ottf_console_spi_device_read(
      ottf_console_get(), sizeof(input_buf), input_buf);
  CHECK(received_data_len == sizeof(kTest64bDataStr));
  CHECK_ARRAYS_EQ(input_buf, kTest64bDataStr, ARRAYSIZE(kTest64bDataStr));

  LOG_INFO("Sending 256B data to Host...");
  LOG_INFO("%s", kTest256bDataStr);
  LOG_INFO("SYNC: Waiting for console data");
  received_data_len = ottf_console_spi_device_read(
      ottf_console_get(), sizeof(input_buf), input_buf);
  CHECK(received_data_len == sizeof(kTest256bDataStr));
  CHECK_ARRAYS_EQ(input_buf, kTest256bDataStr, ARRAYSIZE(kTest256bDataStr));

  LOG_INFO("Sending 1KB data to Host...");
  for (int i = 1; i <= 2; i++) {
    LOG_INFO("Round: %d", i);
    LOG_INFO("%s", kTest1KbDataStr);
    LOG_INFO("SYNC: Waiting for console data");
    received_data_len = ottf_console_spi_device_read(
        ottf_console_get(), sizeof(input_buf), input_buf);
    CHECK(received_data_len == sizeof(kTest1KbDataStr));
    CHECK_ARRAYS_EQ(input_buf, kTest1KbDataStr, ARRAYSIZE(kTest1KbDataStr));
  }

  LOG_INFO("Sending 4KB data to Host...");
  LOG_INFO("%s", kTest4KbDataStr);
  LOG_INFO("SYNC: Waiting for console data");
  received_data_len = ottf_console_spi_device_read(
      ottf_console_get(), sizeof(input_buf), input_buf);
  CHECK(received_data_len == sizeof(kTest4KbDataStr));
  CHECK_ARRAYS_EQ(input_buf, kTest4KbDataStr, ARRAYSIZE(kTest4KbDataStr));

  // Verify that reading data byte-by-byte using `ottf_console_getc` matches the
  // expected output. This function is crucial in the UJSON OTTF console data
  // pipeline.
  memset(&input_buf, 0, sizeof(input_buf));
  LOG_INFO("SYNC: Waiting for console data");
  for (int i = 0; i < sizeof(kTest4KbDataStr); i++) {
    status_t s = ottf_console_getc(ottf_console_get());
    CHECK_STATUS_OK(s);
    input_buf[i] = (uint8_t)s.value;
  }
  CHECK_ARRAYS_EQ(input_buf, kTest4KbDataStr, ARRAYSIZE(kTest4KbDataStr));

  return true;
}
